﻿namespace Peel;

class Program
{
    static void Main(string[] args)
    {
        Console.OutputEncoding = System.Text.Encoding.UTF8;
        List<string> argList = Utils.GetArgsList(args);
        if(argList.Count > 1)
        {
            Utils.WriteLine("参数过多.", ConsoleColor.Red);
            return;
        }
        string sourceDir = string.Empty;
        if (argList.Count == 0)
            sourceDir = Directory.GetCurrentDirectory();
        else
            sourceDir = argList[0];
        Utils.WriteLine($"🍌“去皮”目标: {sourceDir}", ConsoleColor.Blue);
        if(!Directory.Exists(sourceDir))
        {
            Utils.WriteLine($"路径 [{sourceDir}] 不存在", ConsoleColor.Red);
            return;
        }
        Utils.WriteLine("开始“去皮”？ (y/n)", ConsoleColor.Blue);
        if((Console.ReadLine()??"").ToLower() != "y")
        {
            Utils.WriteLine("操作已终止。", ConsoleColor.Red);
            return; 
        }

        try
        {
            Utils.WriteLine("🍌🍌🍌", ConsoleColor.Blue);
            var subDirs = Directory.GetDirectories(sourceDir).ToList();
            var fileMap = CheckWillConflicts(subDirs);
            var conflicts = fileMap.Where(x => x.Value.Count > 1).ToList();
            if (conflicts.Any())
            {
                Utils.WriteLine("以下文件名在多个子目录中出现，“去皮”将导致文件冲突，请手动处理。", ConsoleColor.Red);
                foreach (var conflict in conflicts)
                {
                    Utils.Write($"{conflict.Key}", ConsoleColor.Red, ConsoleColor.Blue);
                    Utils.Write("\t出现于:\t", ConsoleColor.DarkGray);
                    Utils.Write(string.Join(", ", conflict.Value), ConsoleColor.Red);
                    Utils.WriteLine("\n");
                }
                Utils.WriteLine("操作已终止。", ConsoleColor.Red);
                return;
            }
            
            var dirsToRename = GetDirectoryWithSameNameFiles(subDirs);

            if (dirsToRename.Any())
            {
                Utils.WriteLine("下列文件中存在与文件夹同名的子项：", ConsoleColor.DarkYellow);
                foreach (var dir in dirsToRename)
                {
                    Utils.WriteLine($"{dir}\\ -> ({Path.GetFileName(dir)})", ConsoleColor.DarkYellow);
                }
                Utils.WriteLine("是否创建临时目录作为中转(将花费更多时间😑) (y/n)", ConsoleColor.Blue);
                if((Console.ReadLine()??"").ToLower() != "y")
                {
                    Utils.WriteLine("操作已终止。", ConsoleColor.Red);
                    return; 
                }
                string tmpName = $"tmp_{Guid.NewGuid()}";
                string tmpDir = Path.Combine(sourceDir, tmpName);
                if(Directory.Exists(tmpDir))
                {
                    Utils.WriteLine($"临时目录 [{tmpDir}] 已存在(这都重复？☹️)，无法执行操作。", ConsoleColor.Red);
                    return;
                }
                Directory.CreateDirectory(tmpDir);
                Utils.WriteLine($"已创建临时目录 [{tmpDir}] ", ConsoleColor.Green);

                foreach (var subDir in subDirs)
                {
                    Utils.MoveContents(subDir, tmpDir);
                    Directory.Delete(subDir, true);
                }
                Utils.WriteLine($"已将所有内容移动到临时目录 [{tmpDir}] ", ConsoleColor.Green);
                Utils.MoveContents(tmpDir, sourceDir);
                Directory.Delete(tmpDir, true);
                Utils.WriteLine($"已将所有内容移动回源目录 [{sourceDir}] ", ConsoleColor.Green);
            }
            else
            {
                foreach (var subDir in subDirs)
                {
                    Utils.MoveContents(subDir, sourceDir);
                    Directory.Delete(subDir, true);
                }
                Utils.WriteLine($"已将所有内容移动回源目录 [{sourceDir}] ", ConsoleColor.Green);
            }
            Utils.WriteLine("🍌“去皮”完成。", ConsoleColor.Green);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"发生错误：{ex.Message}");
        }
    }

    public static List<string> GetDirectoryWithSameNameFiles(List<string> subDirs)
    {
        var result = new List<string>();

        foreach (var subDir in subDirs)
        {
            var dirName = Path.GetFileName(subDir);
            var files = Directory.GetFiles(subDir);
            var dirs = Directory.GetDirectories(subDir);
            bool haseSameNameItem = files.Any(f => Path.GetFileName(f).Equals(dirName)) 
                                    || dirs.Any(d => Path.GetFileName(d).Equals(dirName));
            if (haseSameNameItem)
            {
                result.Add(subDir);
            }
        }
        return result;
    }

    static Dictionary<string, List<string>> CheckWillConflicts(List<string> secondaryDirs)
    {
        var pathMap = new Dictionary<string, List<string>>();

        foreach (var dir in secondaryDirs)
        {
            var allFiles = Directory.GetFiles(dir);
            foreach (var file in allFiles)
            {
                string name = Path.GetFileName(file);
                if(!pathMap.ContainsKey(name))
                    pathMap[name] = new List<string>();
                pathMap[name].Add(dir);
            }
            var allDir = Directory.GetDirectories(dir);
            foreach (var subDir in allDir)
            {
                string name = Path.GetFileName(subDir);
                if(!pathMap.ContainsKey(name))
                    pathMap[name] = new List<string>();
                pathMap[name].Add(dir);
            }
        }

        return pathMap;
    }

}

public static class Utils
{
    public static List<string> GetArgsList(string[] args)
    {
        List<string> argsList = new List<string>();
        for (int i = 0; i < args.Length; i++)
        {
            argsList.Add(args[i]);
        }
        return argsList;
    }

    public static void WriteLine(string text, ConsoleColor? foreColor = null, ConsoleColor? backColor = null)
    {
        if (backColor.HasValue)
            Console.BackgroundColor = backColor.Value;
        if (foreColor.HasValue)
            Console.ForegroundColor = foreColor.Value;
        Console.WriteLine(text);
        Console.ResetColor();
    }

    public static void Write(string text, ConsoleColor? foreColor = null, ConsoleColor? backColor = null)
    {
        if (backColor.HasValue)
            Console.BackgroundColor = backColor.Value;
        if (foreColor.HasValue)
            Console.ForegroundColor = foreColor.Value;
        Console.Write(text);
        Console.ResetColor();
    }

    public static void MoveContents(string source, string destination)
    {
        string[] files = Directory.GetFiles(source);
        foreach (string file in files)
        {
            string fileName = Path.GetFileName(file);
            string destinationFilePath = Path.Combine(destination, fileName);
            File.Move(file, destinationFilePath);
        }

        string[] directories = Directory.GetDirectories(source);
        foreach (string directory in directories)
        {
            string directoryName = new DirectoryInfo(directory).Name;
            string destinationDirectoryPath = Path.Combine(destination, directoryName);
            Directory.Move(directory, destinationDirectoryPath);
        }
    }
}

